package com.yuand.config;


import com.yuand.entity.SysPermission;
import com.yuand.entity.SysRole;
import com.yuand.entity.SysUser;
import com.yuand.service.SysPermissionService;
import com.yuand.service.SysRoleService;
import com.yuand.service.SysUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author yuandong
 * @date 2021/4/17 10:26
 * 自定义UserRealm  只需要继承 AuthorizingRealm,重现里面的方法
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private SysUserService userService;
    @Autowired
    private SysRoleService roleService;
    @Autowired
    private SysPermissionService permissionService;

    /**
     * 1.这个是认证的方法
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了认证的方法.....cation");

        //强转成在Controller中使用的token
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;

        SysUser user = userService.selectUserByName(userToken.getUsername());

        //如果查不到这个用户，则抛异常，抛IndexController中写好的异常
        if (user == null) {
            return null;
        }
        //密码认证，shiro来做；密码的匹配比对，不用自己写，直接放到这个方法里面即可
        //这里的加密方式可以是MD5加密，但更多的是使用MD5盐值加密
        //注意该方法的第一个参数，需要放入user,这样在授权的时候subject.getPrincipal();就可以拿到这个用户
        return new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());


    }

    /**
     * 2.这个是授权的方法
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权的方法....zation");
        //拿到当前登录的用户
        String userName =(String) principalCollection.iterator().next();
        SysUser currentUser = userService.selectUserByName(userName);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if (currentUser != null) {
            info.addRoles(this.getUserRoles(currentUser.getUserId()));
            info.addStringPermissions(this.getUserPermissions(currentUser.getUserId()));
        }

        return info;
    }


    //得到用户角色集合
    private Set<String> getUserRoles(int userId) {
        List<SysRole> roleList = this.roleService.selectRolesByUserId(userId);
        Set<String> roles = new HashSet<String>();
        //如果是空就直接返回
        if (CollectionUtils.isEmpty(roleList)) {
            return roles;
        }
        //如果不是空就得到角色编号添加进集合中
        for (SysRole role : roleList) {
            roles.add(role.getRoleName());
        }
        return roles;
    }

    //得到用户权限集合
    private Set<String> getUserPermissions(int userId) {
        List<SysPermission> permissionList = this.permissionService.selectPermissionsByUserId(userId);
        Set<String> permissions = new HashSet<String>();
        //如果是空就直接返回
        if (CollectionUtils.isEmpty(permissionList)) {
            return permissions;
        }
        //如果不是空就得到角色编号添加进集合中
        for (SysPermission permission : permissionList) {
            permissions.add(permission.getPermissions());
        }
        System.out.println("该用户所有的权限："+permissions.toString());
        return permissions;
    }


}
